//
//  UIViewController+ZTRouter.m
//  ZTRouter
//
//  Created by 黄露 on 2019/5/30.
//  Copyright © 2019 huanglu. All rights reserved.
//

#import "UIViewController+ZTRouter.h"
#import <objc/runtime.h>
#import "ZTRouterManager.h"
#import "UIViewController+GLTransition.h"
#import "GLPushCustomAnimation.h"
#import "GLPresentCutomAnimation.h"
#import "GLPopCustomAnimation.h"


@implementation UIViewController (ZTRouter)

+ (void) load {
    // 交换viewDidLoad 方法
    Method originMethod_viewDidLoad = class_getInstanceMethod([self class], @selector(viewDidLoad));
    Method swizzleMethod_routerDidLoad = class_getInstanceMethod([self class], @selector(router_viewDidLoad));
    // 交换viewWillAppear 方法
    Method originMethod_viewWillAppear = class_getInstanceMethod([self class], @selector(viewWillAppear:));
    Method swizzleMethod_routerViewWillAppear = class_getInstanceMethod([self class], @selector(router_viewWillAppear:));
    
    BOOL didMethod = class_addMethod([self class], @selector(viewDidLoad), class_getMethodImplementation([self class],  @selector(router_viewDidLoad)), method_getTypeEncoding(swizzleMethod_routerDidLoad));
    if (didMethod) {
        class_replaceMethod([self class], @selector(router_viewDidLoad), class_getMethodImplementation([self class], @selector(viewDidLoad)), method_getTypeEncoding(originMethod_viewDidLoad));
    }
    else {
        method_exchangeImplementations(originMethod_viewDidLoad, swizzleMethod_routerDidLoad);
    }
    
    BOOL didWillMethod = class_addMethod([self class], @selector(viewWillAppear:), class_getMethodImplementation([self class],  @selector(router_viewWillAppear:)), method_getTypeEncoding(swizzleMethod_routerViewWillAppear));
    if (didWillMethod) {
        class_replaceMethod([self class], @selector(router_viewWillAppear:), class_getMethodImplementation([self class], @selector(viewWillAppear:)), method_getTypeEncoding(originMethod_viewWillAppear));
    }
    else {
        method_exchangeImplementations(originMethod_viewWillAppear, swizzleMethod_routerViewWillAppear);
    }
}

- (void) router_viewDidLoad {
    [self router_viewDidLoad];
    if (self.navigationController) {
        [self.navigationController gl_registerBackInteractiveTransitionWithDirection:GLPanEdgeLeft eventBlcok:^{
            [self popForParam:nil completion:nil];
        }];
    } else {
        [self  gl_registerBackInteractiveTransitionWithDirection:GLPanEdgeLeft eventBlcok:^{
            [self popForParam:nil completion:nil];
        }];
    }
}

- (void) router_viewWillAppear:(BOOL)animation {
    [self router_viewWillAppear:animation];
}


- (void) setRoute:(ZTRouterObject *)route {
    objc_setAssociatedObject(self, @selector(setRoute:), route, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (ZTRouterObject *) route {
    id config = objc_getAssociatedObject(self, @selector(setRoute:));
    return config;
}

- (void) push:(NSString *)name param:(nullable id)param {
    UIViewController *vc = [[ZTRouterManager shared] pushToName:name params:param];
    [self nativePush:vc animation:true];
}

- (void) pushToPath:(NSString *)path param:(nullable id)param {
    UIViewController *vc = [[ZTRouterManager shared] pushToPath:path query:param];
    [self nativePush:vc animation:true];
}


- (void) replace:(NSString *)name param:(nullable id)param {
    UIViewController *vc = [[ZTRouterManager shared] replaceToName:name params:param];
    [self nativePush:vc animation:true];
}

- (void) replaceToPath:(NSString *)path param:(nullable id)param {
    UIViewController *vc = [[ZTRouterManager shared] replaceToPath:path params:param];
    [self nativePush:vc animation:true];
}

- (void) popForParam:(nullable id)param completion:(void (^ _Nullable)(void))completion {
    [[ZTRouterManager shared] popForParam:param];
    [self dismissViewControllerAnimated:true completion:^{
        if (completion) {
            completion();
        }
    }];
}

- (void) popToRootForParam:(nullable id)param completion:(void (^ _Nullable)(void))completion {
    UIViewController *vc = [[ZTRouterManager shared] popToRootForParam:param];
    [self nativePop:vc animation:true];
}

- (void) popToName:(NSString *)name param:(nullable id)param completion:(void (^ _Nullable)(void))completion {
    UIViewController *vc = [[ZTRouterManager shared] popToName:name params:param];
    [self nativePop:vc animation:true];
}

- (void) popToPath:(NSString *)path param:(nullable id)param completion:(void (^ _Nullable)(void))completion {
    UIViewController *vc = [[ZTRouterManager shared] popToPath:path params:param];
    [self nativePop:vc animation:true];
}

- (void) nativePush:(UIViewController *)vc animation:(BOOL)animation transiton:(GLTransitionManager*)transition {
    if (vc) {
        if ([vc isKindOfClass:[UINavigationController class]]) {
            [self gl_presentViewControler:vc withAnimation:transition];
        } else {
            UINavigationController *navc = [[UINavigationController alloc] initWithRootViewController:vc];
            [self nativePush:navc animation:animation transiton:transition];
        }
    } else {
        NSLog(@"未找到对应的vc");
    }
}

- (void) nativePush:(UIViewController *)vc animation:(BOOL)animation {
    GLTransitionManager *transition = [[GLPushCustomAnimation alloc] init];
    if (self.animationType == ZTRouterAnimationType_pop) {
        transition = [[GLPopCustomAnimation alloc] init];
    }
    if (self.animationType == ZTRouterPushMode_push) {
        transition = [[GLPushCustomAnimation alloc] init];
    }
    if (self.animationType == ZTRouterPushMode_present) {
        transition = [[GLPresentCutomAnimation alloc] init];
    }
    [self nativePush:vc animation:true transiton:transition];
}

- (void) nativePop:(UIViewController *)vc animation:(BOOL)animation {
    GLTransitionManager *transition = [[GLPopCustomAnimation alloc] init];
    if (vc) {
        if ([vc isKindOfClass:[UINavigationController class]]) {
            [self gl_presentViewControler:vc withAnimation:transition];
        } else {
            UINavigationController *navc = [[UINavigationController alloc] initWithRootViewController:vc];
            [self nativePop:navc animation:true];
        }
    } else {
        NSLog(@"未找到对应的vc");
    }
}

- (void) setAnimationType:(ZTRouterAnimationType)animationType {
    objc_setAssociatedObject(self, @selector(setAnimationType:), @(animationType), OBJC_ASSOCIATION_ASSIGN);
}

- (ZTRouterAnimationType) animationType {
    id type = objc_getAssociatedObject(self, @selector(setAnimationType:));
    return [type integerValue];
}

@end
